package cn.xz.hfsk.net;

import static android.content.ContentValues.TAG;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import com.google.gson.Gson;

import cn.xz.hfsk.bean.BaseResponse;
import cn.xz.hfsk.util.HttpLogger;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import android.content.Context;
import android.util.Log;


/**
 * OkHttp的工具类
 * 
 */
public class OkHttpUtil {
    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final Gson gson = new Gson();
    private static OkHttpClient mOkHttpClient = null;
    private static OkHttpUtil okHttpUtil = null;
    private static final String NET_REQUEST_ERR = "请求错误，请稍后再试！";//请求返回http状态码非正常
    private static final String NET_PARSE_ERR = "解析错误，请稍后再试！";//请求返回http状态码非正常
    private static int mConnectedTime = 10;
    private static int mReadTime = 20;

    /**
     * 获得单例模式
     *
     * @return
     */
    public static OkHttpUtil get() {
        if (okHttpUtil == null || mOkHttpClient == null) {
            synchronized (OkHttpUtil.class) {
                if (okHttpUtil == null) {
                    okHttpUtil = new OkHttpUtil();
                }
                if (mOkHttpClient == null) {
                    HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLogger());
                    logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                    mOkHttpClient = new OkHttpClient.Builder()
                            .addNetworkInterceptor(logInterceptor)
                            .connectTimeout(mConnectedTime, TimeUnit.SECONDS)
                            .readTimeout(mReadTime, TimeUnit.SECONDS)
                            .build();
                }
            }
        }
        return okHttpUtil;

    }

    public static void post(String url){
        get();
        Log.e("debug-->Post:",url);
        final Request request = new Request.Builder().url(url).build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "onFailure: ---->" + e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){

                }
            }
        });

    }

    public static void get(String url,Callback callback){
        get();
        final Request request = new Request.Builder().url(url).build();
        mOkHttpClient.newCall(request).enqueue(callback);
    }


    /**
     * post异步提交json数据
     *
     * @param url
     * @param json
     */
    public <T extends BaseResponse> void postJson(final Context context, String url, String json, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder().url(url).post(body).tag(context).build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * post异步提交json数据
     *
     * @param url
     * @param json
     */
    public <T extends BaseResponse> void postJson(final Context context, Headers headers, String url, String json, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder().url(url).post(body).headers(headers).tag(context).build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * post异步提交form表单
     */
    public <T extends BaseResponse> void postForm(final Context context, Headers headers, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = null;
        if (okhttpResponseHandle != null) {
            okhttpResponseHandle.setFormParams(new FormBody.Builder());
            request = new Request.Builder().url(url).post(okhttpResponseHandle.addFormParams(okhttpResponseHandle.getFormParams().build())).headers(headers).tag(context).build();
        }
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * post异步提交form表单
     */
    public <T extends BaseResponse> void postForm(final Context context,FormBody.Builder form,String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = null;
        if (okhttpResponseHandle != null) {
            if(form == null){
                okhttpResponseHandle.setFormParams(new FormBody.Builder());
            }else{
                okhttpResponseHandle.setFormParams(form);
            }
            request = new Request.Builder().url(url).post(form.build()).tag(context).build();
            //  request = new Request.Builder().url(url).post(okhttpResponseHandle.addFormParams(okhttpResponseHandle.getFormParams().build())).tag(context).build();
        }
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * put异步提交form表单
     */
    public <T extends BaseResponse> void putForm(final Context context, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = null;
        if (okhttpResponseHandle != null) {
            okhttpResponseHandle.setFormParams(new FormBody.Builder());
            request = new Request.Builder().url(url).put(okhttpResponseHandle.addFormParams(okhttpResponseHandle.getFormParams().build())).tag(context).build();
        }
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * delete异步提交form表单
     */
    public <T extends BaseResponse> void deleteForm(final Context context, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = null;
        if (okhttpResponseHandle != null) {
            okhttpResponseHandle.setFormParams(new FormBody.Builder());
            request = new Request.Builder().url(url).delete().tag(context).build();
        }
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * delete异步提交,不要传任何参数
     */
    public <T extends BaseResponse> void delete(final Context context, Headers headers, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = new Request.Builder().url(url).delete().headers(headers).tag(context).build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * delete异步提交,不要传任何参数
     */
    public <T extends BaseResponse> void delete(final Context context, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = new Request.Builder().url(url).delete().tag(context).build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * delete异步提交json数据
     */
    public <T extends BaseResponse> void deleteJson(final Context context, Headers headers, String url, String json, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder().url(url).delete().headers(headers).tag(context).build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * get异步获取数据
     */
    public static <T extends BaseResponse> void get(final Context context, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        get();
        Request request = new Request.Builder().url(url).build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * get异步获取数据
     */
    public <T extends BaseResponse> void get(final Context context, Headers headers, String url, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        if (!isNetworkAvailable(context, okhttpResponseHandle))
            return;
        Request request = new Request.Builder().url(url).headers(headers).addHeader("Connection", "close").build();
        handleCallback(request, context, reponseClass, okhttpResponseHandle);
    }

    /**
     * 回调
     */
    private static <T extends BaseResponse> void handleCallback(final Request request, final Context context, final Class<T> reponseClass, final OkhttpResponseHandle<T> okhttpResponseHandle) {
        Call call = mOkHttpClient.newCall(request);
        if (okhttpResponseHandle != null) {
            okhttpResponseHandle.setContext(context);
            okhttpResponseHandle.sendStartMessage(call, request);
        }
        call.enqueue(new Callback() {
            public void onFailure(Call call, IOException e) {
                //异常
                if (okhttpResponseHandle != null) {
                    //如果不是主动取消,是真正的异常
                    if (!call.isCanceled()) {
                        okhttpResponseHandle.sendFailureMessage(call.request(), e);
                        //okhttpResponseHandle.sendToastMessage(NETWORK_INSTABILITY);
                        okhttpResponseHandle.sendFinishMessage();
                    }
                }
            }


            public void onResponse(Call call, Response response) {
                if (!response.isSuccessful()) {
                    if (okhttpResponseHandle != null) {
                        // okhttpResponseHandle.sendFailureMessage(call.request(), new IOException("Unexpected code " + response));
                        if (response.code() == 401) {
                            okhttpResponseHandle.sendToastMessage("用户认证失败");
                        } else if (response.code() == 403) {
                            okhttpResponseHandle.sendToastMessage("无访问权限");
                        } else {
                            okhttpResponseHandle.sendToastMessage(NET_REQUEST_ERR);
                        }
                        okhttpResponseHandle.sendFinishMessage();
                    }
                } else {
                    try {
                        if (response.body() != null && response.body().charStream() != null) {
                            //如果这里打印一次,下面在解析一次就会抛出异常
                            String responseString = response.body().string();
                            //responseString = Utils.toUTF8(responseString);
                            //Log.e("response.body():",responseString);
                            //LogUtil.LLJi("==================================================");

                            //解析json成对象

                            Response responseTemp = response.newBuilder().body(ResponseBody.create(response.body().contentType(), responseString)).build();
                            //System.out.println("返回数据："+responseTemp.body().string());
                            T gsonResponse = gson.fromJson(responseTemp.body().string(), reponseClass);

                            //解析完成且请求没有被取消
                            if (gsonResponse != null && !call.isCanceled()) {
                                //弹出返回信息
/*                                if (gsonResponse.getStatusInfo() != null && okhttpResponseHandle.isNeedShowStatusInfo())
                                    okhttpResponseHandle.sendToastMessage(gsonResponse.getStatusInfo());*/
                                //  if (gsonResponse.isStatus()==true) {
                                //新的接口
                                if (okhttpResponseHandle != null) {
                                    okhttpResponseHandle.sendSuccessMessage(gsonResponse);
                                }
/*                                } else {
                                    //老的接口
                                            if (okhttpResponseHandle != null) {
                                                okhttpResponseHandle.sendSuccessMessage(gsonResponse);
                                            }

                                }*/
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        if (okhttpResponseHandle != null) {
                            okhttpResponseHandle.sendFailureMessage(request, e);
                            okhttpResponseHandle.sendToastMessage(NET_PARSE_ERR);
                        }
                    } finally {
                        //
                        if (okhttpResponseHandle != null) {
                            okhttpResponseHandle.sendFinishMessage();
                        }
                    }
                }
            }
        });
    }

    /**
     * 判断网络是否可以使用，不可以就回调
     */
    private static <T extends BaseResponse> boolean isNetworkAvailable(Context context, OkhttpResponseHandle<T> okhttpResponseHandle) {

        okhttpResponseHandle.networkHandler(context);

        if (!NetWorkUtil.isNetworkAvailable(context)) {
            okhttpResponseHandle.networkUnAvailable(context);
            return false;
        }
        return true;
    }
}
